#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
//#include <vector>
//#include <string>
//#include <set>
//#include <algorithm>
#include <cassert>
#include <cstring>
#include <list>

using namespace std;



//右值引用
//namespace test
//{
//	class string
//	{
//	public:
//		typedef char* iterator;
//		iterator begin()
//		{
//			return _str;
//		}
//		iterator end()
//		{
//			return _str + _size;
//		}
//		string(const char* str = "")
//			:_size(strlen(str))
//			, _capacity(_size)
//		{
//			//cout << "string(char* str)" << endl;
//			_str = new char[_capacity + 1];
//			strcpy(_str, str);
//		}
//		// s1.swap(s2)
//		void swap(string& s)
//		{
//			::swap(_str, s._str);
//			::swap(_size, s._size);
//			::swap(_capacity, s._capacity);
//		}
//		// 拷贝构造
//		string(const string& s)
//			:_str(nullptr)
//		{
//			cout << "string(const string& s) -- 深拷贝" << endl;
//			string tmp(s._str);
//			swap(tmp);
//		}
//		// 赋值重载
//		string& operator=(const string& s)
//		{
//			cout << "string& operator=(string s) -- 深拷贝" << endl;
//			string tmp(s);
//			swap(tmp);
//			return *this;
//		}
//
//		// 移动构造
//		string(string&& s)
//			:_str(nullptr)
//			, _size(0)
//			, _capacity(0)
//		{
//			cout << "string(string&& s) -- 移动语义" << endl;
//			swap(s);
//		}
//
//		// 移动赋值
//		string& operator=(string&& s)
//		{
//			cout << "string& operator=(string&& s) -- 移动语义" << endl;
//			swap(s);
//			return *this;
//		}
//		~string()
//		{
//			delete[] _str;
//			_str = nullptr;
//		}
//		char& operator[](size_t pos)
//		{
//			assert(pos < _size);
//			return _str[pos];
//		}
//		void reserve(size_t n)
//		{
//			if (n > _capacity)
//			{
//				char* tmp = new char[n + 1];
//				strcpy(tmp, _str);
//				delete[] _str;
//				_str = tmp;
//				_capacity = n;
//			}
//		}
//		void push_back(char ch)
//		{
//			if (_size >= _capacity)
//			{
//				size_t newcapacity = _capacity == 0 ? 4 : _capacity * 2;
//				reserve(newcapacity);
//			}
//			_str[_size] = ch;
//			++_size;
//			_str[_size] = '\0';
//		}
//
//		string& operator+=(char ch)
//		{
//			push_back(ch);
//			return *this;
//		}
//		const char* c_str() const
//		{
//			return _str;
//		}
//
//		string operator+(char c)
//		{
//			string tmp(*this);
//			tmp += c;
//			return tmp;
//		}
//
//	private:
//		char* _str;
//		size_t _size;
//		size_t _capacity; // 不包含最后做标识的\0
//	};
//
//
//
//	string to_string(int value)
//	{
//		bool flag = true;
//		if (value < 0)
//		{
//			flag = false;
//			value = 0 - value;
//		}
//		bit::string str;
//		while (value > 0)
//		{
//			int x = value % 10;
//			value /= 10;
//			str += ('0' + x);
//		}
//		if (flag == false)
//		{
//			str += '-';
//		}
//		std::reverse(str.begin(), str.end());
//		return str;
//	}
//}
//
//
//int main()
//{
//	//test::string s = test::string("123456") + 'c'; //对于临时变量返回值 如果使用拷贝构造则深拷贝会损失非常多的性能
//	//对于以往的传值返回构造 如果以左值引用临时变量则编译器会先释放临时变量再构造 此时会出错 但是右值构造会先构造(swap)再释放对象 这是编译器的一种策略
//
//	//test::string s = test::to_string(1234); //在编译器优化之前，需要先将str拷贝一份临时变量，然后销毁str，再使用临时变量拷贝构造s
//	//但是编译器优化后，在str销毁前，直接移动构造了
//  //s = test::to_string(4321); //同样的移动赋值会先将函数返回对象移动构造为临时对象然后临时对象进行移动赋值
//	//C++11的其他容器都增加了右值插入版本
//	//这是因为对于某些容器嵌套 例如下面这种情况 如果插入的是某个函数的返回值
//	//在编译器不优化的情况下 函数返回值会先被拷贝一份作为临时变量 然后再拷贝构造为对象插入外包容器中
//	//在编译器优化的情况下，可能优化为一次拷贝构造
//	list<test::string> t;
//
//	//t.push_back("1234");
//	t.push_back(test::to_string(1234)); //对于这种情况，编译器不敢擅自做主直接构造
//	//编译器必须先将返回值构造为临时变量再由临时变量构造去插入
//	//使用移动构造 str会将_str先交换给临时变量，临时变量再交换给插入链表的值 所以观察的现象是两次移动构造
//	
//  
//	return 0;
//}


////完美转发(万能引用)
//void Fun(int& x) { cout << "左值引用" << endl; }
//void Fun(const int& x) { cout << "const 左值引用" << endl; }
////std::forward 完美转发在传参的过程中保留对象原生类型属性
//void Fun(int&& x) { cout << "右值引用" << endl; }
//void Fun(const int&& x) { cout << "const 右值引用" << endl; }
//// 模板中的&&不代表右值引用，而是万能引用，其既能接收左值又能接收右值。
//// 模板的万能引用只是提供了能够接收同时接收左值引用和右值引用的能力，
//// 但是引用类型的唯一作用就是限制了接收的类型，后续使用中都退化成了左值，
//// 我们希望能够在传递过程中保持它的左值或者右值的属性, 就需要用我们下面学习的完美转发
//template<typename T>
//void PerfectForward(T&& t) //右值引用模板参数 当传入的是左值则会折叠属性为左值，当传入的是右值时属性会保持为右值
//{
//	//Fun(t); //当右值被函数识别后在函数内就成为左值，因为右值引用是对左值的一种拷贝
//	Fun(forward<T>(t)); //在某些情况下我们希望右值属性一直保持，传递下去
//}
//int main()
//{
//	PerfectForward(10);           // 右值
//	int a;
//	PerfectForward(a);            // 左值
//	PerfectForward(std::move(a)); // 右值
//	const int b = 8;
//	PerfectForward(b);      // const 左值
//	PerfectForward(std::move(b)); // const 右值
//
//	//move(左值) 对左值修饰后返回其右值属性的值 但对象本身不变，还是原传入的左值对象
//
//	return 0;
//}

void fun(int& x)
{
	cout << "左值" << endl;
}

void fun(int&& x)
{
	cout << "右值" << endl;
}

int main()
{
	//可以取地址和赋值的为左值
	//不能取地址的是右值

	int a = 1;
	int& b = a; //左值引用a
	
	a + 1; //右值

	//int& c = a + 2; //左值引用不能引用右值
	int&& c = a + b; //右值引用本身是对右值的一种拷贝，在特定区域开空间存入右值

	fun(a + b);
	fun(a);
	fun(move(a));

	return 0;
}